#include "viml/instruction.h"
#include <gtest/gtest.h>
#include <vector>

namespace viml {

// 定义InstructionList类型
using InstructionList = std::vector<Instruction>;

// 为Instruction类添加相等操作符
bool operator==(const Instruction& lhs, const Instruction& rhs) {
    return lhs.opcode == rhs.opcode &&
           lhs.a == rhs.a &&
           lhs.b == rhs.b &&
           lhs.c == rhs.c &&
           lhs.bx == rhs.bx;
}

class InstructionTest : public ::testing::Test {
protected:
    // 可以在这里添加测试所需的设置代码
};

TEST_F(InstructionTest, InstructionCreation) {
    // 测试指令创建
    Instruction instr(OpCode::LOAD_CONST, 1, 42);
    
    // 验证指令字段
    EXPECT_EQ(instr.opcode, OpCode::LOAD_CONST);
    EXPECT_EQ(instr.a, 1);
    EXPECT_EQ(instr.b, 42);
    EXPECT_EQ(instr.c, 0); // 默认值
}

TEST_F(InstructionTest, InstructionToString) {
    // 测试指令转字符串
    Instruction instr(OpCode::ADD, 1, 2, 3);
    std::string str = instr.to_string();
    
    // 验证字符串表示包含关键信息
    EXPECT_NE(str.find("ADD"), std::string::npos);
    EXPECT_NE(str.find("1"), std::string::npos);
    EXPECT_NE(str.find("2"), std::string::npos);
    EXPECT_NE(str.find("3"), std::string::npos);
}

TEST_F(InstructionTest, OpCodeConversion) {
    // 测试操作码转换
    EXPECT_EQ(to_string(OpCode::LOAD_CONST), "LOAD_CONST");
    EXPECT_EQ(to_string(OpCode::ADD), "ADD");
    EXPECT_EQ(to_string(OpCode::SUB), "SUB");
    EXPECT_EQ(to_string(OpCode::MUL), "MUL");
    EXPECT_EQ(to_string(OpCode::DIV), "DIV");
    EXPECT_EQ(to_string(OpCode::RETURN_OP), "RETURN");
    
    // 测试无效操作码
    EXPECT_EQ(to_string(static_cast<OpCode>(-1)), "UNKNOWN");
}

TEST_F(InstructionTest, InstructionEquality) {
    // 测试指令相等性
    Instruction instr1(OpCode::LOAD_CONST, 1, 42);
    Instruction instr2(OpCode::LOAD_CONST, 1, 42);
    Instruction instr3(OpCode::LOAD_CONST, 2, 42);
    
    EXPECT_TRUE(instr1 == instr2);
    EXPECT_FALSE(instr1 == instr3);
}

TEST_F(InstructionTest, InstructionList) {
    // 测试指令列表
    InstructionList instructions;
    instructions.push_back(Instruction(OpCode::LOAD_CONST, 0, 42));
    instructions.push_back(Instruction(OpCode::LOAD_CONST, 1, 24));
    instructions.push_back(Instruction(OpCode::ADD, 2, 0, 1));
    
    // 验证指令列表内容
    ASSERT_EQ(instructions.size(), 3);
    EXPECT_EQ(instructions[0].opcode, OpCode::LOAD_CONST);
    EXPECT_EQ(instructions[1].opcode, OpCode::LOAD_CONST);
    EXPECT_EQ(instructions[2].opcode, OpCode::ADD);
    
    // 验证指令参数
    EXPECT_EQ(instructions[0].a, 0);
    EXPECT_EQ(instructions[0].b, 42);
    EXPECT_EQ(instructions[2].a, 2);
    EXPECT_EQ(instructions[2].b, 0);
    EXPECT_EQ(instructions[2].c, 1);
}

} // namespace viml